package com.objectcarpentry.kaylee.gstreamer.jobs;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.util.URI;
import org.gstreamer.ElementFactory;
import org.gstreamer.GstObject;
import org.gstreamer.TagList;
import org.gstreamer.TagMergeMode;
import org.gstreamer.Bus.EOS;
import org.gstreamer.Bus.ERROR;
import org.gstreamer.Bus.TAG;
import org.gstreamer.elements.PlayBin;

import com.objectcarpentry.kaylee.Track;
import com.objectcarpentry.kaylee.gstreamer.internal.Utilities;

public class MetadataJob extends Job {

	
	protected Collection<Track> tracks;
	
	protected PlayBin playbin;
	
	private Map<URI, TagList> map;
	
	public MetadataJob(String name, Collection<Track> tracks) {
		super(name);
		this.tracks = tracks;
	}

	@Override
	protected IStatus run(IProgressMonitor monitor) {
		
		monitor.beginTask("Aquiring metadata", tracks.size());
		
		
		
		Map<URI, TagList> internalMap = new HashMap<URI, TagList>();
		
		playbin =  new PlayBin("TagReader");
		playbin.setVideoSink(ElementFactory.make("fakesink", "videosink"));
		playbin.setAudioSink(ElementFactory.make("fakesink", "audiosink"));
		
		
		playbin.getBus().connect(new EOS(){
			@Override
			public void endOfStream(GstObject source) {
				getThread().interrupt();
			}
		});
		playbin.getBus().connect(new ERROR(){
			@Override
			public void errorMessage(GstObject source, int code, String message) {
				getThread().interrupt();
			}
		});
				
		TagBag tags;
		
		for (Track t : tracks){
			monitor.subTask("Processing " + URI.decode(t.getLocation().lastSegment()));
			playbin.setURI(java.net.URI.create(t.getLocation().toString()));
			
			tags = new TagBag();
			playbin.getBus().connect(tags);
			
			playbin.setState(org.gstreamer.State.PLAYING);
			
			try {
				Thread.sleep(50);
			} catch (InterruptedException e){
				System.out.println("interrupted");
			}
			
			playbin.setState(org.gstreamer.State.NULL);
			playbin.getBus().disconnect(tags);
			
			List<TagList> allTags = tags.getTags();
			TagList merged = null;
			for (TagList tl : allTags){
				merged = tl.merge(merged, TagMergeMode.REPLACE);
			}
			
			Utilities.storeMetadata(t, merged);
			monitor.worked(1);
		}
		
		map = internalMap;
		return Status.OK_STATUS;
		
	}
	
	
	class TagBag implements TAG {
		private List<TagList> tags;
		@Override
		public void tagsFound(GstObject source, TagList tagList) {
			getTags().add(tagList);
		}
		
		public List<TagList> getTags(){
			if (tags == null){
				tags = Collections.synchronizedList(new ArrayList<TagList>());
			}
			return tags;
		}
	}
	
	

}
